home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 1145 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  4.2 KB

  1. From: damian@molly.cs.monash.edu.au (Damian Conway)
  2. Message-ID: <damian.829693837@molly.cs.monash.edu.au>
  3. X-Original-Date: Tue, 16 Apr 1996 22:30:37 +0000 (GMT)
  4. Path: in1.uu.net!bounce-back
  5. Date: 18 Apr 96 00:47:16 GMT
  6. Approved: fjh@cs.mu.oz.au
  7. Subject: Re: methods for accessing attributes
  8. Organization: Monash University
  9. X-Nntp-Posting-User: damian
  10. Newsgroups: comp.std.c++
  11. References: <9604160147.AA25931@grace>
  12. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  13.     iQBFAgUBMXWRN+EDnX0m9pzZAQGsSgGAg2t2+w2Ky0EfULMwXJ3EMhQuCPk+yZ8J
  14.     v02Xzx6B7WfmWxGlGAQVhO+QFdDoQNpw
  15.     =TSJr
  16.  
  17. Steve Clamage writes (or forwards, I suspect):
  18.  
  19. >Has there been any consideration of adding to the standard
  20. >a way of overloading access to instance variables, so that
  21. >code that directly accesses a variable can be made to call 
  22. >an access function if the class is modified to need it?
  23.  
  24. >For instance, let's say we've got:
  25. >    
  26. >    class Display {
  27. >    public:
  28. >        int wid, hgt;
  29. >    }
  30.  
  31. >If lots of code already exists like the following:
  32.  
  33. >    void blah(Display &d)
  34. >    {
  35. >        d.wid = 80;
  36. >    }
  37.  
  38. >And now suppose that we want Display to do something when
  39. >the width is changed--- has there been any consideration of adding
  40. >a way of doing this?  (besides changing all the direct accesses
  41. >to function calls)   
  42.  
  43. Something like this will do what you want (note that you'll still have to
  44. recompile everything that accesses the data members):
  45.  
  46.  
  47.     template <class Owner, class Type>
  48.     class AccessControlled
  49.     {
  50.     typedef Type (Owner::*Filter)(const Type&);
  51.  
  52.     public:
  53.     AccessControlled(Owner * owner, Filter read = 0, Filter write = 0)
  54.     : This(owner)
  55.     , readFilter(read)
  56.     , writeFilter(write)
  57.     {}
  58.  
  59.     operator Type(void)
  60.     {
  61.         if (readFilter)
  62.             return (This->*readFilter)(value);
  63.         else
  64.             return value;
  65.     }
  66.  
  67.     AccessControlled& operator= (const Type& newval)
  68.     {
  69.         if (writeFilter)
  70.             value = (This->*writeFilter)(newval);
  71.         else
  72.             value = newval;
  73.         return *this;
  74.     }
  75.  
  76.     private:
  77.     Owner* This;
  78.     Type value;
  79.     Filter readFilter;
  80.     Filter writeFilter;
  81.     };
  82.  
  83.  
  84.  
  85. And then you can change class Display thus:
  86.  
  87.     class Display
  88.     {
  89.     public:
  90.     AccessControlled<Display,int> wid;
  91.     AccessControlled<Display,int> hgt;
  92.     AccessControlled<Display,int> dph;
  93.  
  94.  
  95.     // NEED A CTOR TO INITIALIZE THE FILTERS FOR THE ABOVE DATA MEMBERS
  96.  
  97.     Display(void)
  98.     : wid(this,logAccess)        // NO VALUE CHECKING FOR wgt
  99.     , hgt(this,0,checkVal)        // NO ACCESS LOGGING FOR hgt
  100.     , dph(this,logAccess,checkSize)    // BOTH LOGGING AND CHECKING FOR dph
  101.     {}
  102.  
  103.     private:
  104.     int logAccess(const int& val)
  105.     {
  106.         // DO WHATEVER WITH CURRENT VALUE OF WID BEFORE PASSING IT OUT
  107.         // EG: LOG THE ACCESS.....
  108.  
  109.         clog << "Accessing value " << val << endl;
  110.         return val;
  111.     }
  112.  
  113.     int checkVal(const int& newval)
  114.     {
  115.         // DO WHATEVER WITH NEW VALUE FOR VAR BEFORE PASSING IT IN
  116.         // EG: MAKE SURE IT'S POSITIVE, NON-ZERO....
  117.  
  118.         if (newval<=0)
  119.             return 1;
  120.         else
  121.             return newval;
  122.     }
  123.  
  124.     int checkSize(const int& newval)
  125.     {
  126.         // DO WHATEVER WITH NEW VALUE FOR VAR BEFORE PASSING IT IN
  127.         // EG: MAKE SURE IT'S IN THE RANGE [-10..10]
  128.  
  129.         if (newval<-10)
  130.             return -10;
  131.         else if (newval>10)
  132.             return 10;
  133.         else
  134.             return newval;
  135.     }
  136.     };
  137.  
  138.  
  139. >If [access functions are required], then I'd like to stick with some sort
  140. >of standard naming convention... but I've seen all kinds of different 
  141. >variations...
  142.  
  143. >So, which of these do people think is the most acceptable?
  144.  
  145. >    1)
  146. >        class Display {
  147. >            int wid;
  148. >        public:
  149. >            int get_wid();
  150. >            void set_wid(int);
  151. >        }
  152.  
  153. I greatly prefer this approach.
  154. It's clear, obvious, and says explicitly what it means.
  155.  
  156. damian
  157. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  158.   who: Damian Conway               email: damian@bruce.cs.monash.edu.au
  159. where: Dept. Computer Science      phone: +61-3-565-5184
  160.        Monash University             fax: +61-3-565-5146
  161.        Clayton 3168                quote: "A pessimist is never disappointed."
  162.        AUSTRALIA
  163. ---
  164. [ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
  165. [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
  166. [ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
  167. [ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
  168. [ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
  169.